package com.motong.gongdan.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.motong.gongdan.entity.*;
import com.motong.gongdan.mapper.ExceptionInfoMapper;
import com.motong.gongdan.util.LoginUtil;
import com.motong.gongdan.vo.system.device.vo.DeviceDataVo;
import com.motong.gongdan.vo.system.exceptionHandle.query.ExceptionGetListQuery;
import com.motong.gongdan.vo.system.exceptionHandle.vo.ExceptionGetListVo;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ExceptionInfoService extends ServiceImpl<ExceptionInfoMapper, ExceptionInfo> {

    @Resource
    private UserService userService;

    @Resource
    private DeviceInfoService deviceInfoService;

    @Resource
    private LampRequestService lampRequestService;

    @Resource
    private LampTypeUserService lampTypeUserService;

    @Resource
    private ExceptionInfoMapper exceptionInfoMapper;

    @Resource
    private ExceptionTypeService exceptionTypeService;

    @Resource
    private DeviceLampTypeService deviceLampTypeService;

    @Resource
    private LampRequestNoticeService lampRequestNoticeService;

    @Resource
    private LampRequestDetailService lampRequestDetailService;


    public void h5Edit(boolean isUpdate, ExceptionInfo exceptionInfo) {
        Integer currentUserId = LoginUtil.getLoginUserId();
        exceptionInfo.setUpdateTime(new Date()).setUpdateUser(currentUserId);
        if (!isUpdate) {
            exceptionInfo.setCreateTime(new Date()).setUpdateUser(currentUserId);
        }
        if (isUpdate) {
            ExceptionInfo oriException = this.getById(exceptionInfo.getId());
            if (Objects.nonNull(exceptionInfo.getExceptionType()) && !exceptionInfo.getExceptionType().equals(Optional.ofNullable(oriException.getExceptionType()).orElse(0L))) {
                ExceptionType exceptionType = exceptionTypeService.getById(exceptionInfo.getExceptionType());
                this.sendLampRequestByDeal(oriException.getDeviceId(), exceptionType);
            }
        }
        this.saveOrUpdate(exceptionInfo);
    }

    public void sendLampRequestByDeal(Long deviceId, ExceptionType exceptionType) {
        if (Objects.nonNull(exceptionType)) {
            this.sendLampRequestByLampTypeId(deviceId,exceptionType.getLampType());
        }

    }

    public void sendLampRequestByLampTypeId(Long deviceId, Long lampTypeId) {
        if (Objects.nonNull(lampTypeId)) {
            Integer currentUserId = LoginUtil.getLoginUserId();
            User user = new User();
            user.setName("设备");
            if (Objects.nonNull(currentUserId)) {
                user = userService.getById(currentUserId);
            }
            LambdaQueryWrapper<DeviceLampType> deviceLampTypeQW = new LambdaQueryWrapper<DeviceLampType>().eq(DeviceLampType::getDeviceId, deviceId)
                    .eq(DeviceLampType::getLampTypeId, lampTypeId);
            // 获取联络灯到人配置
            DeviceLampType deviceLampType = deviceLampTypeService.getOne(deviceLampTypeQW);
            String noticeUserIds;
            String noticeUserNames;
            // 创建联络灯请求
            if (Objects.nonNull(deviceLampType)) {
                noticeUserIds = deviceLampType.getInfoUser();
                noticeUserNames = deviceLampType.getInfoUserName();
            } else {
                Set<String> userIds = lampTypeUserService.list(new LambdaQueryWrapper<LampTypeUser>().eq(LampTypeUser::getLampTypeId, lampTypeId))
                        .stream().map(i -> i.getUserId().toString()).collect(Collectors.toSet());
                noticeUserIds = String.join(",", userIds);
                noticeUserNames = userService.listByIds(userIds).stream().map(User::getName).collect(Collectors.joining(","));
            }
            if (StringUtils.hasLength(noticeUserIds) && StringUtils.hasLength(noticeUserNames)) {
                LampRequest lampRequest = new LampRequest().setCreateTime(new Date()).setCreateUser(currentUserId).setUpdateTime(new Date()).setUpdateUser(currentUserId)
                        .setDealState(0).setType(lampTypeId).setDeviceId(deviceId).setDealUser(noticeUserIds)
                        .setDealUserName(noticeUserNames);
                lampRequestService.save(lampRequest);
                // 语音播报相关信息
                DeviceInfo deviceInfo = deviceInfoService.getById(deviceId);
                lampRequestNoticeService.saveByLampTypeId(lampRequest.getType(), lampRequest.getId(), deviceInfo.getDeviceSn());
                LampRequestDetail lampRequestDetail = new LampRequestDetail().setLampRequestId(lampRequest.getId())
                        .setContent(Objects.isNull(user) ? "" : user.getName().concat("发起了联络灯请求。")).setCreateTime(new Date())
                        .setCreateUser(LoginUtil.getLoginUserId()).setUpdateTime(new Date()).setUpdateUser(LoginUtil.getLoginUserId());
                lampRequestDetailService.save(lampRequestDetail);
            }
        }

    }

    /**
     * 异常信息列表
     *
     * @param page  分页信息
     * @param query 请求参数
     * @return 列表数据
     */
    public Page<ExceptionGetListVo> getList(Page<ExceptionInfo> page, ExceptionGetListQuery query) {
        Page<ExceptionGetListVo> data = exceptionInfoMapper.getList(page, query);
        data.getRecords().forEach(i -> {
            i.setLampColorName(Objects.nonNull(i.getLampColor()) && i.getLampColor() == 1 ? "红灯" : "黄灯");
            i.setDate(DateUtil.formatDate(i.getCreateDateTime())).setStartTime(DateUtil.format(i.getCreateDateTime(), "HH:mm"));
            if (Objects.nonNull(i.getEndDateTime())) {
                i.setEndTime(DateUtil.format(i.getEndDateTime(), "HH:mm"));
                long betweenSecond = DateUtil.between(i.getCreateDateTime(), i.getEndDateTime(), DateUnit.SECOND);
                i.setDurationHour(BigDecimal.valueOf(betweenSecond).divide(BigDecimal.valueOf(3600L), 2, RoundingMode.UP));
            }
        });
        return data;
    }

    public void deviceDealException(DeviceDataVo data) {
        DeviceInfo deviceInfo = data.getDeviceInfo();
        LambdaQueryWrapper<ExceptionInfo> exceptionQW = new LambdaQueryWrapper<ExceptionInfo>().eq(ExceptionInfo::getDeviceId, deviceInfo.getId())
                .eq(StringUtils.hasLength(data.getExceptionLampColor()),ExceptionInfo::getLampColor, data.getExceptionLampColor()).isNull(ExceptionInfo::getEndTime).isNull(ExceptionInfo::getExceptionReason)
                .orderByDesc(ExceptionInfo::getCreateTime).last("LIMIT 1");
        ExceptionInfo exceptionInfo = this.getOne(exceptionQW);
        if (Objects.nonNull(exceptionInfo)) {
            data.setExceptionLampColor(Optional.ofNullable(data.getExceptionLampColor()).orElse(exceptionInfo.getLampColor().toString()));
            Page<ExceptionType> typePage = new Page<>(Long.parseLong(data.getCause()), 1L);
            LambdaQueryWrapper<ExceptionType> exceptionTypeQW = new LambdaQueryWrapper<ExceptionType>()
                    .eq(ExceptionType::getGroupId,deviceInfo.getGroupId()).eq(ExceptionType::getLampColor, data.getExceptionLampColor())
                    .orderByDesc(ExceptionType::getCreateTime);
            Page<ExceptionType> page = exceptionTypeService.page(typePage, exceptionTypeQW);
            List<ExceptionType> records = page.getRecords();
            if (!CollectionUtils.isEmpty(records)) {
                ExceptionType exceptionType = records.get(0);
                exceptionInfo.setExceptionReason(exceptionType.getExceptionReason()).setExceptionType(exceptionType.getId())
                        .setGroupId(exceptionInfo.getGroupId()).setUpdateTime(new Date());
                this.sendLampRequestByDeal(deviceInfo.getId(), exceptionType);
                this.updateById(exceptionInfo);
            }
        }
    }
}

